#include <iostream>
#include <unistd.h>
#include <pthread.h>

// 共享资源
int cnt = 0;
// 互斥锁，使用静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 条件变量，使用静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *Count(void * args)
{
    // 将线程设置为分离状态，结束时自动回收资源
    pthread_detach(pthread_self());
    // 转换参数类型，这里是线程编号
    uint64_t number = (uint64_t)args;
    std::cout << "pthread: " << number << " create success" << std::endl;

    while(true)
    {
        // 加锁保护临界区
        pthread_mutex_lock(&mutex);
        
        // 调用pthread_cond_wait等待条件满足
        // 重要说明：
        // 1. pthread_cond_wait会自动释放mutex并使线程等待
        // 2. 当被唤醒时，会自动重新获取mutex
        // 3. 这里没有使用while循环检查条件，因为示例中不关心具体条件
        pthread_cond_wait(&cond, &mutex);
        
        // 临界区：增加计数并打印
        std::cout << "pthread: " << number << " ， cnt: " << cnt++ << std::endl;
        
        // 释放锁
        pthread_mutex_unlock(&mutex);
    }
}

int main()
{
    // 创建5个工作线程
    for(uint64_t i = 0; i < 5; i++)
    {
        pthread_t tid;
        pthread_create(&tid, nullptr, Count, (void*)i);
        usleep(1000);  // 短暂休眠，避免线程创建过快
    }
    
    // 主线程休眠3秒，等待工作线程都准备就绪
    sleep(3);
    std::cout << "main thread ctrl begin: " << std::endl;

    while(true) 
    {
        sleep(1);  // 每秒唤醒一次
        
        // 使用broadcast唤醒所有等待的线程
        pthread_cond_broadcast(&cond);
        // 也可以使用signal只唤醒一个线程
        // pthread_cond_signal(&cond);
        
        std::cout << "signal one thread..." << std::endl;
    }

    return 0;
}

/*
// 这是一个售票系统的示例
void *getTicket(void *args)
{
    // 将void*参数转换为threadData类型
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    
    while (true)
    {
        // 在访问共享资源(tickets)前加锁
        // 两种加锁方式：使用传入的锁或全局锁
        // pthread_mutex_lock(td->lock);
        pthread_mutex_lock(&lock);
        
        if(tickets > 0)  // 还有票可以售卖
        {
            usleep(1000);  // 模拟售票过程耗时
            printf("who=%s, get a ticket: %d\n", name, tickets);
            tickets--;     // 售出一张票
            pthread_mutex_unlock(td->lock);
        }
        else  // 没票了
        {
            pthread_mutex_unlock(td->lock);
            // 这里可以增加等待逻辑
        }
        
        // 模拟售票后的其他操作耗时
        usleep(13);
    }
    
    printf("%s ... quit\n", name);
    return nullptr;
}
*/